/**
 * 通用HTTP请求封装
 * 提供GET、POST、PUT、DELETE、文件上传、文件下载等方法
 */
import type { RequestClientConfig } from '@vben/request';

import type { PageParams, PageResult, Result } from './types/modules/base';

import { baseRequestClient, requestClient } from './request';

/**
 * HTTP请求方法封装
 */
export const Http = {
  /**
   * GET请求
   * @param url 请求地址
   * @param params 请求参数
   * @param config 请求配置
   * @returns Promise<Result<T>>
   */
  get<T = any>(
    url: string,
    params?: Record<string, any>,
    config?: RequestClientConfig,
  ): Promise<Result<T>> {
    return requestClient.get<Result<T>>(url, {
      params,
      ...config,
    });
  },

  /**
   * POST请求
   * @param url 请求地址
   * @param data 请求数据
   * @param config 请求配置
   * @returns Promise<Result<T>>
   */
  post<T = any>(
    url: string,
    data?: Record<string, any>,
    config?: RequestClientConfig,
  ): Promise<Result<T>> {
    return requestClient.post<Result<T>>(url, data, config);
  },

  /**
   * PUT请求
   * @param url 请求地址
   * @param data 请求数据
   * @param config 请求配置
   * @returns Promise<Result<T>>
   */
  put<T = any>(
    url: string,
    data?: Record<string, any>,
    config?: RequestClientConfig,
  ): Promise<Result<T>> {
    return requestClient.put<Result<T>>(url, data, config);
  },

  /**
   * DELETE请求
   * @param url 请求地址
   * @param params 请求参数
   * @param config 请求配置
   * @returns Promise<Result<T>>
   */
  delete<T = any>(
    url: string,
    params?: Record<string, any>,
    config?: RequestClientConfig,
  ): Promise<Result<T>> {
    return requestClient.delete<Result<T>>(url, {
      params,
      ...config,
    });
  },

  /**
   * 分页请求
   * @param url 请求地址
   * @param params 分页参数
   * @param config 请求配置
   * @returns Promise<Result<PageResult<T>>>
   */
  page<T = any>(
    url: string,
    params: PageParams & Record<string, any>,
    config?: RequestClientConfig,
  ): Promise<Result<PageResult<T>>> {
    return requestClient.get<Result<PageResult<T>>>(url, {
      params,
      ...config,
    });
  },

  /**
   * 文件上传
   * @param url 请求地址
   * @param formData FormData对象
   * @param config 请求配置
   * @returns Promise<Result<T>>
   */
  upload<T = any>(
    url: string,
    formData: FormData,
    config?: RequestClientConfig,
  ): Promise<Result<T>> {
    return requestClient.post<Result<T>>(url, formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      ...config,
    });
  },

  /**
   * 文件下载
   * @param url 请求地址
   * @param params 请求参数
   * @param filename 文件名
   * @param config 请求配置
   * @returns Promise<void>
   */
  async download(
    url: string,
    params?: Record<string, any>,
    filename?: string,
    config?: RequestClientConfig,
  ): Promise<void> {
    const response = await requestClient.get(url, {
      params,
      responseType: 'blob',
      ...config,
    });

    // 从响应头获取文件名
    let downloadFilename = filename;
    const contentDisposition = response.headers?.['content-disposition'];
    if (!downloadFilename && contentDisposition) {
      const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
      const matches = filenameRegex.exec(contentDisposition);
      if (matches !== null && matches[1]) {
        downloadFilename = matches[1].replaceAll(/['"]/g, '');
      }
    }

    // 如果没有指定文件名，使用当前时间戳
    if (!downloadFilename) {
      downloadFilename = `download_${Date.now()}`;
    }

    // 创建Blob对象
    const blob = new Blob([response.data]);

    // 创建下载链接
    const downloadLink = document.createElement('a');
    downloadLink.href = URL.createObjectURL(blob);
    downloadLink.download = downloadFilename;

    // 触发下载
    document.body.append(downloadLink);
    downloadLink.click();

    // 清理
    downloadLink.remove();
    URL.revokeObjectURL(downloadLink.href);
  },

  /**
   * 刷新令牌请求
   * 用于刷新访问令牌，使用基础请求客户端
   * @param url 请求地址
   * @param data 请求数据
   * @param config 请求配置
   * @returns Promise<T>
   */
  refreshToken<T = any>(
    url: string,
    data?: Record<string, any>,
    config?: RequestClientConfig,
  ): Promise<T> {
    return baseRequestClient.post<T>(url, data, {
      withCredentials: true,
      ...config,
    });
  },
};

/**
 * 导出默认对象
 */
export default Http;
